﻿using System;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using System.Configuration;
using System.ComponentModel;
using System.Diagnostics;
using System.ServiceProcess;
using Entities = Vision.Core.Entities;
using Components = Vision.Core.Components;

namespace Vision.Server
{
    public partial class VisionController : ServiceBase
    {
        private Thread ScheduleWorker { get; set; }
        private DateTime ServiceStartup { get; set; }
        
        /// <summary>
        /// 
        /// </summary>
        public VisionController()
        {
            InitializeComponent();                                    
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            this.ServiceStartup = DateTime.Now;
            this.ScheduleWorker = new Thread(() => this.ScheduleWorker_Process());
            this.ScheduleWorker.Start();  
        }

        /// <summary>
        /// 
        /// </summary>
        protected override void OnStop()
        {
            this.ScheduleWorker.Abort();
            this.ScheduleWorker = null;     
        }

        /// <summary>
        /// 
        /// </summary>
        private void ScheduleWorker_Process()
        {
            while (true){
                using (Components.ActivityScheduler activityScheduler = new Components.ActivityScheduler(ConfigurationManager.AppSettings["VisionCatalog"])){
                    DateTime timeStamp = DateTime.Now;

                    List<Entities.Scheduling.VisionActvitySchedule> polledSchedules = activityScheduler.PollVisionSchedules(timeStamp);
                    foreach (var schedule in polledSchedules){
                        schedule.LastError = string.Empty;
                        try{
                            if (schedule.ScheduleCanExpire && schedule.ScheduleFinishDate <= timeStamp){
                                schedule.Active = false;                                    
                            }
                            else if (schedule.ScheduleNextRunDate.HasValue){
                                if (schedule.ScheduleNextRunDate.Value > this.ServiceStartup){
                                    SendQueueMessage(schedule);
                                    schedule.ScheduleLastRunDate = DateTime.Now;
                                }
                            }
                            schedule.ScheduleNextRunDate = activityScheduler.ComputeNextRunTime(schedule);
                        }
                        catch (Exception ex){
                            schedule.LastError = ex.ToString();
                        }
                        finally{
                            activityScheduler.SaveVisonSchedule(schedule);
                        }
                    }

                }
                Thread.Sleep(10000);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="schedule"></param>
        private void SendQueueMessage(Entities.Scheduling.VisionActvitySchedule schedule)
        {            
            using (Components.ActivityQueueSender queueSender = new Components.ActivityQueueSender(schedule.ActivityQueue)){
                Entities.Activities.VisionActivityMessage vaMessage = new Entities.Activities.VisionActivityMessage();
                vaMessage.ActivityKey = schedule.ActivityKey;
                vaMessage.ActivityParams = schedule.ActivityParams;
                queueSender.SendVisionActivityMessage(vaMessage);
            }
        } 

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] { new VisionController() };
            ServiceBase.Run(ServicesToRun);
        }
    }
}
